package com.tomecode.rvr.generator.formate;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.tmatesoft.svn.core.SVNNodeKind;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc.SVNStatusType;

import com.tomecode.rvr.generator.InReport;
import com.tomecode.rvr.generator.ReportFormate;
import com.tomecode.rvr.generator.util.Utilities;

/**
 * 
 * Formating output data in report file
 * 
 * @author Frastia Tomas
 * 
 */
public final class FileFormateWriter {

	/**
	 * all lines
	 */
	private final List<Line> lines;

	private final InReport inReport;
	private final ReportFormate reportType;
	private final File reportFile;

	/**
	 * Construktor
	 * 
	 * @param report
	 *            repor file
	 * @param reportType
	 *            {@link ReportFormate}
	 * @param inReport
	 *            {@link InReport}
	 */
	public FileFormateWriter(File report, ReportFormate reportType, InReport inReport) {
		this.lines = new ArrayList<Line>();
		this.inReport = inReport;
		this.reportFile = report;
		this.reportType = reportType;
	}

	/**
	 * append new line to {@link FileFormateWriter}
	 * 
	 * @param svnNodeKind
	 * @param author
	 * @param svnStatusType
	 * @param revision
	 * @param commitedDate
	 * @param path
	 */
	public final void append(SVNNodeKind svnNodeKind, String author, SVNStatusType svnStatusType, SVNRevision revision, Date commitedDate, String path) {
		if (revision == null) {
			lines.add(new Line(svnNodeKind, author, svnStatusType, -1, null, commitedDate, path));
		} else {
			lines.add(new Line(svnNodeKind, author, svnStatusType, revision.getNumber(), revision.getDate(), commitedDate, path));
		}
	}

	/**
	 * generate report file
	 * 
	 * @throws IOException
	 */
	public final void generate() throws IOException {
		BufferedWriter bufferedWriter = null;
		try {
			bufferedWriter = new BufferedWriter(new FileWriter(reportFile));
			// value spliter
			String spliter = reportType.getSplit();

			// formate lines
			int maxKind = 0, maxAuthor = 0, maxStatus = 0, maxRevisionDate = 0, maxRevisionNumber = 0, maxCommitDate = 0;
			for (Line line : lines) {
				if (inReport.isKind()) {
					maxKind = countMax(line.getKind(), maxKind);
				}
				if (inReport.isAuthor()) {
					maxAuthor = countMax(line.getAuthor(), maxAuthor);
				}
				if (inReport.isStatus()) {
					maxStatus = countMax(line.getStatus(), maxStatus);
				}
				if (inReport.isRevisionDate()) {
					maxRevisionDate = countMax(line.getRevisionDate(), maxRevisionDate);
				}
				if (inReport.isRevisionNumber()) {
					maxRevisionNumber = countMax(line.getRevisionNumber(), maxRevisionNumber);
				}
				if (inReport.isCommitedDate()) {
					maxCommitDate = countMax(line.getCommitedDate(), maxCommitDate);
				}

			}

			// print to file
			for (Line line : lines) {
				StringBuilder sb = new StringBuilder();

				if (inReport.isKind()) {
					sb.append(line.getKind() + Utilities.createEmptyString(countMidle(line.getKind(), maxKind)));
					sb.append(spliter);
				}
				if (inReport.isAuthor()) {
					sb.append(line.getAuthor() + Utilities.createEmptyString(countMidle(line.getAuthor(), maxAuthor)));
					sb.append(spliter);
				}
				if (inReport.isStatus()) {
					sb.append(line.getStatus() + Utilities.createEmptyString(countMidle(line.getStatus(), maxStatus)));
					sb.append(spliter);
				}
				if (inReport.isRevisionDate()) {
					sb.append(line.getRevisionDate() + Utilities.createEmptyString(countMidle(line.getRevisionDate(), maxRevisionDate)));
					sb.append(spliter);
				}
				if (inReport.isRevisionNumber()) {
					sb.append(line.getRevisionNumber() + Utilities.createEmptyString(countMidle(line.getRevisionNumber(), maxRevisionNumber)));
					sb.append(spliter);
				}
				if (inReport.isCommitedDate()) {
					sb.append(line.getCommitedDate() + Utilities.createEmptyString(countMidle(line.getCommitedDate(), maxCommitDate)));
					sb.append(spliter);
				}
				if (inReport.isPath()) {
					sb.append(line.getPath());
					sb.append(spliter);
				}
				sb.append("\n");
				bufferedWriter.write(sb.toString());
			}

		} finally {
			if (bufferedWriter != null) {
				bufferedWriter.close();
			}
		}
	}

	private final int countMax(String value, int max) {
		int length = value.length();
		if (length >= max) {
			return length;
		}
		return max;
	}

	private final int countMidle(String value, int max) {
		if (value.length() > max) {
			return value.length() - max;
		}
		return max - value.length();
	}
}
